home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Aminet 22
/
Aminet 22 (1997)(GTI - Schatztruhe)[!][Dec 1997].iso
/
Aminet
/
dev
/
e
/
amigae33a.lha
/
E_v3.3a
/
Src.lha
/
Src
/
Utils
/
FindString13.e
< prev
next >
Wrap
Text File
|
1997-05-12
|
10KB
|
361 lines
OPT OSVERSION=37
MODULE 'tools/async',
'tools/ctype',
'tools/easygui',
'amigalib/lists',
'dos/dos',
'exec/lists',
'exec/nodes',
'intuition/intuition',
'libraries/asl',
'asl'
ENUM ERR_NONE, ERR_ADOS, ERR_ASL, ERR_EXAM, ERR_EXNEXT, ERR_GUI,
ERR_LIB, ERR_LOCK, ERR_OPEN, ERR_PATT, ERR_QUIT, ERR_STOP,
ERR_STR, NUM_ERRS
RAISE ERR_ADOS IF AllocDosObject()=NIL,
ERR_ASL IF AllocAslRequest()=NIL,
ERR_EXAM IF Examine()=FALSE,
ERR_LIB IF OpenLibrary()=NIL,
ERR_LOCK IF Lock()=NIL,
ERR_PATT IF ParsePattern()=-1,
ERR_PATT IF ParsePatternNoCase()=-1,
ERR_STR IF String()=NIL
CONST MAXSTR=100, BUFFERSIZE=1000
CONST MAXPATT=MAXSTR*2+2
-> String gadgets
DEF xfindstr[MAXSTR]:STRING, xdirstr[MAXSTR]:STRING,
findstr[MAXSTR]:STRING, dirstr[MAXSTR]:STRING,
findgad, dirgad,
xfpattstr[MAXSTR]:STRING, fpattstr[MAXSTR]:STRING, fpattgad,
fpattbuff[MAXPATT]:STRING
-> Other gadgets
DEF reslist=NIL:PTR TO lh, resgad, gogad,
xrec=TRUE, xcase=TRUE, xword=FALSE, xbrief=FALSE,
rec, case, word, brief,
xpatt=FALSE, patt, pattbuff[MAXPATT]:STRING
-> Other globals
DEF ready=TRUE, gh=NIL:PTR TO guihandle, path[MAXSTR]:STRING,
findfunc=NIL, freq=NIL:PTR TO filerequester
PROC main() HANDLE
StrCopy(xfpattstr, '#?')
newList(NEW reslist)
easyguiA({prog},
[EQROWS,
findgad:=[STR,{s_ignore},'_Find:',xfindstr,MAXSTR,10,0,0,"f"],
[COLS,
[SPACEH],
[CHECK,{c_patt},'P_attern?',xpatt,TRUE,0,"a"],
[CHECK,{c_case},'_Case sensitive?',xcase,TRUE,0,"c"],
[CHECK,{c_word},'_Whole word?',xword,TRUE,0,"w"]
],
[BAR],
[COLS,
dirgad:=[STR,{s_ignore},'_Directory:',xdirstr,MAXSTR,10,0,0,"d"],
[BUTTON,{b_pick},'Pic_k...',0,"k"]
],
[COLS,
fpattgad:=[STR,{s_ignore},'File _Pattern:',xfpattstr,MAXSTR,5,0,0,"p"],
[CHECK,{c_rec},'_Recursive?',xrec,TRUE,0,"r"],
[CHECK,{c_brief},'_Brief output?',xbrief,TRUE,0,"b"]
],
[BAR],
[TEXT,'Results:',NIL,FALSE,5],
resgad:=[LISTV,{l_ignore},'',25,10,reslist,FALSE,0,0],
[BAR],
[COLS,
[SPACEH],
gogad:=[BUTTON,{b_go},'_GO!',0,"g",0,FALSE],
[SPACEH],
[BUTTON,{b_stop},'_Stop',0,"s"],
[SPACEH],
[BUTTON,{b_quit},'_Quit',0,"q"],
[SPACEH]
]
],
[EG_GHVAR,{gh}, NIL])
EXCEPT DO
IF reslist
freeNodes(reslist)
END reslist
ENDIF
IF freq THEN FreeAslRequest(freq)
IF aslbase THEN CloseLibrary(aslbase)
ENDPROC
PROC s_ignore(info, str) IS 0
PROC l_ignore(info, x) IS 0
-> Action functions for option gadgets
PROC c_case(info,bool) IS xcase:=bool
PROC c_word(info,bool) IS xword:=bool
PROC c_rec(info,bool) IS xrec:=bool
PROC c_brief(info,bool) IS xbrief:=bool
PROC c_patt(info,bool) IS xpatt:=bool
PROC b_pick(info)
IF aslbase=NIL
aslbase:=OpenLibrary('asl.library', 37)
-> Only initialise once so position, path, etc. remembered.
freq:=AllocAslRequest(ASL_FILEREQUEST,
[ASLFR_WINDOW, gh.wnd,
ASLFR_TITLETEXT, 'Pick a Directory',
ASLFR_DRAWERSONLY, TRUE,
NIL])
ENDIF
IF RequestFile(freq) THEN setstr(gh, dirgad, freq.drawer)
ENDPROC
PROC b_go(info)
-> Only go if not already going!
IF ready
ready:=FALSE
go()
ready:=TRUE
ENDIF
ENDPROC
PROC b_stop(info)
-> Interrupt if going
IF ready=FALSE THEN Raise(ERR_STOP)
ENDPROC
PROC b_quit(info) IS Raise(ERR_QUIT)
-> Copy current gadget values.
PROC copygadgets()
-> Extract the current strings from the text gadgets.
getstr(gh,findgad); getstr(gh,dirgad)
StrCopy(findstr, xfindstr); StrCopy(dirstr, xdirstr)
rec:=xrec; case:=xcase; word:=xword; brief:=xbrief
getstr(gh,fpattgad)
StrCopy(fpattstr, xfpattstr)
patt:=xpatt
ENDPROC
-> Just scan the selected directory.
PROC go() HANDLE
DEF tmp[MAXSTR]:STRING, p
setdisabled(gh,gogad)
-> Get a copy of current gadget values.
copygadgets()
-> Not much to do if the string is empty...
IF EstrLen(findstr)=0 THEN Raise()
-> Empty the list and redisplay it.
setlistvlabels(gh, resgad, -1)
freeNodes(reslist)
setlistvlabels(gh, resgad, reslist)
IF patt
p:=IF word THEN '((#?[~A-Za-z0-9])|%)' ELSE '#?'
StrCopy(tmp, p); StrAdd(tmp, findstr); StrAdd(tmp, p)
IF case
ParsePattern(tmp, pattbuff, MAXPATT)
findfunc:={find_patt_case}
ELSE
ParsePatternNoCase(tmp, pattbuff, MAXPATT)
findfunc:={find_patt_nocase}
ENDIF
ELSEIF case
findfunc:=IF word THEN {find_word_case} ELSE {find_case}
ELSE
-> Make the findstr lowercase if ignoring case differences.
LowerStr(findstr)
findfunc:=IF word THEN {find_word_nocase} ELSE {find_nocase}
ENDIF
-> Set up pattern buffer.
ParsePatternNoCase(fpattstr, fpattbuff, MAXPATT)
scandir(dirstr)
EXCEPT DO
-> Re-enable the 'Go!' gadget.
setdisabled(gh,gogad,FALSE)
IF exception=ERR_QUIT THEN ReThrow()
ENDPROC
-> The start of the real work.
PROC scandir(s) HANDLE
DEF lock=NIL, fib=NIL:PTR TO fileinfoblock, oldlock, len
len:=EstrLen(path)
lock:=Lock(s, ACCESS_READ)
oldlock:=CurrentDir(lock)
fib:=AllocDosObject(DOS_FIB, NIL)
-> Examine the file.
Examine(lock, fib)
IF fib.direntrytype>=0
-> It's a directory, so examine all the files it contains.
WHILE ExNext(lock, fib)
checkgui(gh)
IF fib.direntrytype<0
IF MatchPatternNoCase(fpattbuff, fib.filename)
scanfile(fib.filename)
ENDIF
ELSEIF rec
-> If directory then call recursively.
StrAdd(path, fib.filename); StrAdd(path, '/')
scandir(fib.filename)
SetStr(path, len)
ENDIF
ENDWHILE
IF IoErr()<>ERROR_NO_MORE_ENTRIES THEN Raise(ERR_EXNEXT)
ENDIF
EXCEPT DO
SetStr(path, len)
IF fib THEN FreeDosObject(DOS_FIB, fib)
IF lock
CurrentDir(oldlock)
UnLock(lock)
ENDIF
SELECT NUM_ERRS OF exception
CASE ERR_ADOS, ERR_EXAM, ERR_EXNEXT, ERR_LOCK
DEFAULT
ReThrow()
ENDSELECT
ENDPROC
-> The real work. Search the file for the findstr.
PROC scanfile(file) HANDLE
DEF fh=NIL, buffer[BUFFERSIZE]:STRING, line=1
fh:=myopen(file, OLDFILE)
WHILE myreadstr(fh, buffer)
checkgui(gh)
IF findfunc(buffer)
report(file, buffer, line)
-> Stop here if being brief.
IF brief THEN Raise()
ENDIF
INC line
ENDWHILE
EXCEPT DO
IF fh THEN myclose(fh)
IF exception<>ERR_OPEN THEN ReThrow()
ENDPROC
-> Use as_Open from tools/async
PROC myopen(file, mode)
DEF fh
IF fh:=as_Open(file, mode, 3, 5000)
RETURN fh
ELSE
Raise(ERR_OPEN)
ENDIF
ENDPROC
-> Close the file opened with myopen().
PROC myclose(fh) IS as_Close(fh)
-> Return FALSE (or NIL) if failed to read string.
PROC myreadstr(fh, s)
DEF res
IF res:=as_FGetS(fh, s, StrMax(s)) THEN SetStr(s, StrLen(s))
ENDPROC res
-> Try to find findstr in s (case sensitive)
PROC find_case(s) IS InStr(s, findstr)<>-1
-> Try to find the word findstr in s (case sensitive)
PROC find_word_case(s)
DEF i=0, len
len:=EstrLen(s)
WHILE i<len
IF -1=(i:=InStr(s, findstr, i))
RETURN FALSE
ELSEIF isword(s, i, EstrLen(findstr))
RETURN TRUE
ELSE
INC i
ENDIF
ENDWHILE
ENDPROC FALSE
-> Try to find findstr in s (not case sensitive)
PROC find_nocase(s) IS lower_find(s, {find_case})
-> Try to find the word findstr in s (not case sensitive)
PROC find_word_nocase(s) IS lower_find(s, {find_word_case})
PROC find_patt_case(s) IS MatchPattern(pattbuff, s)
PROC find_patt_nocase(s) IS MatchPatternNoCase(pattbuff, s)
-> Try to find after lowercasing a copy of s.
PROC lower_find(s, real_find)
DEF tmp[MAXSTR]:STRING
StrCopy(tmp, s)
LowerStr(tmp)
ENDPROC real_find(tmp)
-> Is the bit between i and i+len a complete word in s?
PROC isword(s, i, len)
IF i>0 THEN IF isalnum(s[i-1]) THEN RETURN FALSE
RETURN isalnum(s[i+len])=FALSE
ENDPROC
-> Report the find and update list.
PROC report(f, s, n)
setlistvlabels(gh, resgad, -1)
addNode(reslist, f, s, n)
setlistvlabels(gh, resgad, reslist)
ENDPROC
-> Add a new node to the list.
PROC addNode(list, f, s, n) HANDLE
DEF node=NIL:PTR TO ln, len
NEW node
len:=EstrLen(path)+StrLen(f)+10
IF brief
node.name:=String(len)
StringF(node.name, '\s\s (\d)', path, f, n)
ELSE
filter(s)
node.name:=String(len+EstrLen(s)+4)
StringF(node.name, '\s\s (\d) -> \s', path, f, n, s)
ENDIF
AddTail(list, node)
EXCEPT
IF node
IF node.name THEN DisposeLink(node.name)
END node
ENDIF
ReThrow()
ENDPROC
-> Free a list of nodes and empty it.
PROC freeNodes(list:PTR TO lh)
DEF worknode:PTR TO ln, nextnode
worknode:=list.head -> First node.
WHILE nextnode:=worknode.succ
IF worknode.name THEN DisposeLink(worknode.name)
END worknode
worknode:=nextnode
ENDWHILE
newList(list)
ENDPROC
-> Convert non-printing chars to " " or ".".
PROC filter(s)
WHILE s[]
IF 0=(s[] AND $60)
SELECT $E OF s[]
CASE $0
-> Leave this alone!
CASE $8, $A, $D
-> TAB, linefeed, carriage return.
s[]:=" "
DEFAULT
s[]:="."
ENDSELECT
ENDIF
s++
ENDWHILE
ENDPROC
CHAR 0, '$VER:'
prog:
CHAR ' FindString 1.3', 0, 0